﻿using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Castle.Windsor.Installer;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Yto.Common.Dependency
{
    public class CtnManager : ICtnManager
    {
        private static readonly Lazy<CtnManager> lazy = new Lazy<CtnManager>(() => new CtnManager());

        public static CtnManager Instance { get { return lazy.Value; } }

        public IWindsorContainer Container { get; private set; }

        private IList<IBasicRegister> _registList;

        public CtnManager()
        {
            Container = new WindsorContainer();
            _registList = new List<IBasicRegister>();
            Container.Register(
                Component.For<CtnManager, ICtnManager, ICtnRegister, ICtnResolver>().UsingFactoryMethod(() => this).LifestyleSingleton()
                );
        }

        public void Dispose()
        {
            Container.Dispose();
        }

        public bool IsRegisted(Type type)
        {
            return Container.Kernel.HasComponent(type);
        }

        public bool IsRegisted<T>()
        {
            return Container.Kernel.HasComponent(typeof(T));
        }

        public void Realse(object instance)
        {
            Container.Release(instance);
        }

        public void RegistAssembly(Assembly assembly)
        {
            RegistAssembly(assembly, new RegistrationCfg());
        }

        public void RegistAssembly(Assembly assembly, RegistrationCfg config)
        {
            //var context = new RegistrationCtx(assembly, this, config);

            if (config._InstallAll)
            {
                Container.Install(FromAssembly.Instance(assembly));
            }
            foreach(var item in _registList)
            {
                item.RegistAssembly(assembly,this);
            }

        }

        public T Resolver<T>()
        {
            return Container.Resolve<T>();
        }

        public T Resolver<T>(Type type)
        {
            return (T)Container.Resolve(type);
        }

        public void Regist(Type type, RegisterLifeStyle lifeStyle = RegisterLifeStyle.Singleton)
        {
            Container.Register(setLifeStyle(Component.For(type),lifeStyle));
        }


        public static ComponentRegistration<T> setLifeStyle<T>(ComponentRegistration<T> registration, RegisterLifeStyle lifeStyle)
            where T : class
        {
            switch (lifeStyle)
            {
                case RegisterLifeStyle.Singleton:
                    return registration.LifestyleSingleton();
                case RegisterLifeStyle.Transient:
                    return registration.LifestyleTransient();
                default:
                    return registration;
            }
        }

        public void Regist(Type type, Type implementType, RegisterLifeStyle lifeStyle = RegisterLifeStyle.Singleton)
        {
            Container.Register(setLifeStyle(Component.For(type, implementType).ImplementedBy(implementType), lifeStyle));
        }

        public void AddRegister(IBasicRegister basicRegister)
        {
            _registList.Add(basicRegister);
        }

        public T Resolver<T>(object argumentsAsAnonymousType)
        {
            return Container.Resolve<T>(argumentsAsAnonymousType);
        }

        public object Resolver(Type type)
        {
            return Container.Resolve(type);
        }

        void ICtnRegister.Regist<T, TI>(RegisterLifeStyle lifeStyle)
        {
            Container.Register(setLifeStyle(Component.For<T, TI>().ImplementedBy<TI>(), lifeStyle));
        }
    }
}
